/*****************************************************************************************
   
   Copyright (c) Microsoft Corporation. All rights reserved.

   Use of this code sample is subject to the terms of the Microsoft
   Permissive License, a copy of which should always be distributed with
   this file.  You can also access a copy of this license agreement at:
   http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx

 ****************************************************************************************/

using System;

namespace GrooveWebServicesV12Helpers
{
	/// <summary>
	/// Class describing a Groove identity.
	/// 
	/// Usually you will access an Identity via the Account in which it is contained.
	/// </summary>
	public class Identity : 
		GrooveWebServicesV12HelpersBase,
		GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback
	{
		private GrooveWebServicesV12Helpers.Account m_Account;
		private GrooveWebServicesV12Helpers.Service[] m_AdditionalServices;
			
		private GrooveAccountsWebService.Identity2 m_Identity;
		private GrooveMessagesWebService.GrooveMessages m_GrooveMessages;

		private string m_SpaceSubscriptionID;
		
		internal static System.Collections.SortedList s_SpaceEventManagerSortedList = new System.Collections.SortedList();
		private int m_SpaceEventManagerCount = 0;

		public Identity(GrooveWebServicesV12Helpers.Account i_Account, GrooveAccountsWebService.Identity2 i_Identity)
			: base(i_Identity.Name, i_Identity.URI, i_Identity.URI, i_Account.Context)
		{
			m_Identity = i_Identity;
			m_Account = i_Account;
		}

		public Identity(GrooveAccountsWebService.Identity2 i_Identity, GrooveWebServicesV12Helpers.Context i_Context)
			: base (i_Identity.Name, i_Identity.URI, i_Identity.URI, i_Context)
		{
			m_Identity = i_Identity;
		}

        public Identity(Identity i_Identity, Context i_Context)
            : base(i_Identity.Name, i_Identity.URI, i_Identity.IdentityURL, i_Context)
        {
        }

		#region Identity Properties and Methods

		/// <summary>
		/// Get the Account which contains this Identity.
		/// </summary>
		public GrooveWebServicesV12Helpers.Account Account
		{
			get
			{
				//  If initialized without account, we have to iterate through all accounts to 
				//  find one with matching identity URI
				if (m_Account == null)
				{
					GrooveWebServicesV12Helpers.Account[] Accounts = GrooveWebServicesV12Helpers.Account.GetAccounts(Context);
					foreach (GrooveWebServicesV12Helpers.Account Account in Accounts)
					{
						foreach (GrooveWebServicesV12Helpers.Identity Identity in Account.Identities)
						{
							if (Identity.URI == this.URI)
							{
								m_Account = Account;
								break;
							}
						}
					}
				}

				return m_Account;
			}
		}

		/// <summary>
		/// Get the array of additional Service(s) provided by this Identity.
		/// </summary>
		public GrooveWebServicesV12Helpers.Service[] AdditionalServices
		{
			get
			{
				if (m_AdditionalServices == null)
				{
					System.Collections.ArrayList ServiceArrayList = new System.Collections.ArrayList();
 
					foreach (GrooveAccountsWebService.Service Service in m_Identity.AdditionalServices)
					{
						GrooveWebServicesV12Helpers.Service NewService = new GrooveWebServicesV12Helpers.Service(Service);
						ServiceArrayList.Add(NewService);
					}

					//  Convert array list to array
					m_AdditionalServices = (GrooveWebServicesV12Helpers.Service[])ServiceArrayList.ToArray(typeof(GrooveWebServicesV12Helpers.Service));
				}

				return m_AdditionalServices;
			}
		}

		#endregion

		#region Message Properties and Methods

		public string SendMessage(string i_RecipientURI, string i_Body)
		{
			return this.SendMessage
				(
				new string[] {i_RecipientURI},
				i_Body
				);
		}

		public string SendMessage(string[] i_RecipientURIs, string i_Body)
		{
			GrooveWebServicesV12Helpers.MessageHeader MessageHeader = new GrooveWebServicesV12Helpers.MessageHeader
				(
				m_Account,
				i_RecipientURIs
				);

			GrooveWebServicesV12Helpers.MessageContent MessageContent = new GrooveWebServicesV12Helpers.MessageContent
				(
				m_Account, 
				i_Body
				);

			return this.SendMessage
				(
				MessageHeader,
				MessageContent
				);
		}

		public string SendMessage(string i_RecipientURI, string i_Body, string i_FileURI)
		{
			return this.SendMessage
				(
				new string[] {i_RecipientURI},
				i_Body,
				new string[] {i_FileURI}
				);
		}

		public string SendMessage(string i_RecipientURI, string i_Body, string[] i_FileURIs)
		{
			return this.SendMessage
				(
				new string[] {i_RecipientURI},
				i_Body,
				i_FileURIs
				);
		}

		public string SendMessage(string[] i_RecipientURIs, string i_Body, string i_FileURI)
		{
			return this.SendMessage
				(
				i_RecipientURIs,
				i_Body,
				new string[] {i_FileURI}
				);
		}

		public string SendMessage(string[] i_RecipientURIs, string i_Body, string[] i_FileURIs)
		{
			GrooveWebServicesV12Helpers.MessageHeader MessageHeader = new GrooveWebServicesV12Helpers.MessageHeader
				(
				m_Account,
				i_RecipientURIs,
				false,				// HasVoiceMemo
				true				// HasAttachments
				);

			System.Collections.ArrayList MessageAttachmentArrayList = new System.Collections.ArrayList();
			foreach (string FileURI in i_FileURIs)
			{
				string[] FileURIParts = FileURI.Split(new char[] {'\\', '/'});
				string DisplayName = FileURIParts[FileURIParts.Length - 1];

				GrooveWebServicesV12Helpers.MessageAttachment NewMessageAttachment = new GrooveWebServicesV12Helpers.MessageAttachment
					(
					DisplayName,
					GrooveWebServicesV12Helpers.MessageAttachment.AttachmentType.File,
					FileURI
					);

				MessageAttachmentArrayList.Add(NewMessageAttachment);
			}

			//  Convert array list to array
			GrooveWebServicesV12Helpers.MessageAttachment[] MessageAttachments = (GrooveWebServicesV12Helpers.MessageAttachment[])MessageAttachmentArrayList.ToArray(typeof(GrooveWebServicesV12Helpers.MessageAttachment));

			GrooveWebServicesV12Helpers.MessageContent MessageContent = new GrooveWebServicesV12Helpers.MessageContent
				(
				m_Account, 
				i_Body,
				MessageAttachments
				);

			return this.SendMessage
				(
				MessageHeader,
				MessageContent
				);
		}

		public string SendMessage(GrooveWebServicesV12Helpers.MessageHeader i_MessageHeader, GrooveWebServicesV12Helpers.MessageContent i_MessageContent)
		{
			//  Get initialized reference to web service
			GrooveMessagesWebService.GrooveMessages MessagesWebService = this.GetInitializedMessagesWebService(m_Account.MessagesURI);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to create message
			string MessageURI = MessagesWebService.Create
				(
				i_MessageHeader.RawMessageHeader,
				i_MessageContent.RawMessageContent
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("MessagesWebService::Create, " + TimeSpan.TotalMilliseconds + " ms");
			}

			return MessageURI;
		}

		public string ReplyToMessage(string i_MessageURI, string i_Body)
		{
			GrooveWebServicesV12Helpers.MessageContent MessageContent = new GrooveWebServicesV12Helpers.MessageContent
				(
				m_Account,
				i_Body
				);

			return this.ReplyToMessage
				(
				i_MessageURI,
				true,			// ReplyToAll
				true,			// IncludeOriginalMessage
				null,			// MessageHeader
				MessageContent
				);
		}

		public string ReplyToMessage(string i_MessageURI, string i_Body, string i_AdditionRecipientURI)
		{
			return this.ReplyToMessage
				(
				i_MessageURI,
				i_Body,
				new string [] {i_AdditionRecipientURI}
				);
		}

		public string ReplyToMessage(string i_MessageURI, string i_Body, string[] i_AdditionalRecipientURIs)
		{
			GrooveWebServicesV12Helpers.MessageContent MessageContent = new GrooveWebServicesV12Helpers.MessageContent
				(
				m_Account,
				i_Body
				);

			GrooveWebServicesV12Helpers.MessageHeader MessageHeader = new GrooveWebServicesV12Helpers.MessageHeader
				(
				m_Account,
				i_AdditionalRecipientURIs
				);

			return this.ReplyToMessage
				(
				i_MessageURI,
				true,			// ReplyToAll
				true,			// IncludeOriginalMessage
				MessageHeader,
				MessageContent
				);
		}

		public string ReplyToMessage(string i_MessageURI, bool i_ReplyToAll, bool i_IncludeOriginalMessage, GrooveWebServicesV12Helpers.MessageHeader i_MessageHeader, GrooveWebServicesV12Helpers.MessageContent i_MessageContent)
		{
			//  Get initialized reference to web service
			GrooveMessagesWebService.GrooveMessages MessagesWebService = this.GetInitializedMessagesWebService(i_MessageURI);

			GrooveMessagesWebService.MessageHeader MessageHeader = (i_MessageHeader != null) ? i_MessageHeader.RawMessageHeader : new GrooveMessagesWebService.MessageHeader();
			GrooveMessagesWebService.MessageContent MessageContent = (i_MessageContent != null) ? i_MessageContent.RawMessageContent : new GrooveMessagesWebService.MessageContent();

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to create reply message
			string MessageURI = MessagesWebService.CreateReply
				(
				i_ReplyToAll,
				i_IncludeOriginalMessage,
				MessageHeader,
				MessageContent
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("MessagesWebService::CreateReply, " + TimeSpan.TotalMilliseconds + " ms");
			}

			return MessageURI;
		}

		public string ForwardMessage(string i_MessageURI, string i_Body, string i_RecipientURI)
		{
			return this.ForwardMessage
				(
				i_MessageURI,
				i_Body,
				new string[] {i_RecipientURI}
				);
		}

		public string ForwardMessage(string i_MessageURI, string i_Body, string[] i_RecipientURIs)
		{
			GrooveWebServicesV12Helpers.MessageContent MessageContent = new GrooveWebServicesV12Helpers.MessageContent
				(
				m_Account,
				i_Body
				);

			GrooveWebServicesV12Helpers.MessageHeader MessageHeader = new GrooveWebServicesV12Helpers.MessageHeader
				(
				m_Account,
				i_RecipientURIs
				);

			return this.ForwardMessage
				(
				i_MessageURI,
				MessageHeader,
				MessageContent
				);
		}

		public string ForwardMessage(string i_MessageURI, GrooveWebServicesV12Helpers.MessageHeader i_MessageHeader, GrooveWebServicesV12Helpers.MessageContent i_MessageContent)
		{
			//  Get initialized reference to web service
			GrooveMessagesWebService.GrooveMessages MessagesWebService = this.GetInitializedMessagesWebService(i_MessageURI);

			GrooveMessagesWebService.MessageHeader MessageHeader = (i_MessageHeader != null) ? i_MessageHeader.RawMessageHeader : new GrooveMessagesWebService.MessageHeader();
			GrooveMessagesWebService.MessageContent MessageContent = (i_MessageContent != null) ? i_MessageContent.RawMessageContent : new GrooveMessagesWebService.MessageContent();

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to create forward message
			string MessageURI = MessagesWebService.CreateForward
				(
				MessageHeader,
				MessageContent
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("MessagesWebService::CreateForward, " + TimeSpan.TotalMilliseconds + " ms");
			}

			return MessageURI;
		}

		private GrooveMessagesWebService.GrooveMessages GetInitializedMessagesWebService(string i_TargetURI)
		{
            if ((m_GrooveMessages == null) || Context.ReinitNeeded(m_GrooveMessages.GrooveRequestHeaderValue.GrooveRequestKey))
			{
				m_GrooveMessages = GrooveWebServicesV12Helpers.Message.CreateInitializedMessagesWebService
					(
					m_IdentityURL,
					i_TargetURI,
					Context
					);
			}
			else
			{
				//  Explicitly overwrite target URL and Timeout
				m_GrooveMessages.Url = Context.Host + i_TargetURI;
                m_GrooveMessages.Timeout = Context.Timeout;
			}

			return m_GrooveMessages;
		}

		#endregion

		#region Space Properties, Methods and Events

		/// <summary>
		/// Get the URI for raw web services access to the workspaces to which this Identity belongs.
		/// </summary>
		public string SpacesURI
		{
			get
			{
				return m_Identity.Spaces;
			}
		}

		/// <summary>
		/// Get an array of the Spaces to which this Identity belongs.
		/// </summary>
		public GrooveWebServicesV12Helpers.Space[] StandardSpaces
		{
			get
			{
				return this.GetSpaces("");
			}
		}

		/// <summary>
		/// Get an array of the Spaces to which this Identity belongs.
		/// </summary>
		/// <param name="i_SpaceType">URN that specifies the workspace type. To read workspaces except for Groove File Sharing workspaces, either omit this parameter or set it to an empty string "". To read all the Groove File Sharing workspaces, set it to "urn:groove.net:Groove.Core.Tools.System.TelespaceTypes.GFS". To read information about a specific type of workspace, specify its URN.</param>
		/// <returns>Array of Space objects.</returns>
		public GrooveWebServicesV12Helpers.Space[] GetSpaces(string i_SpaceType)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SPACES_URI,
				Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to provide the list of spaces for this identity
			GrooveSpacesWebService.Space[] Spaces = SpacesWebService.Read(i_SpaceType);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::Read, " + TimeSpan.TotalMilliseconds + " ms");
			}

			//  Create array list of Spaces
			System.Collections.ArrayList SpaceArrayList = new System.Collections.ArrayList();
			foreach (GrooveSpacesWebService.Space Space in Spaces)
			{
				GrooveWebServicesV12Helpers.Space NewSpace = new GrooveWebServicesV12Helpers.Space 
					(
					this,
					Space
					);

				SpaceArrayList.Add(NewSpace);
			}

			//  Return array from array list
			return (GrooveWebServicesV12Helpers.Space[])SpaceArrayList.ToArray(typeof(GrooveWebServicesV12Helpers.Space));
		}

		/// <summary>
		/// Create a new workspace.
		/// </summary>
		/// <param name="i_Name">Specifies the name of the created workspace.</param>
		/// <returns>The URI of the created workspace.</returns>
		public string CreateSpace(string i_Name)
		{
			return int_CreateSpace
				(
				i_Name,
				"",
				GrooveWebServicesV12Helpers.Shared.GROOVE_GENERIC_CREATE_SPACE_TEMPLATE
				);
		}

		/// <summary>
		/// Create a new workspace.
		/// </summary>
		/// <param name="i_Name">Specifies the name of the created workspace.</param>
		/// <param name="i_Description">Specifies the description of the created workspace.</param>
		/// <returns>The URI of the created workspace.</returns>
		public string CreateSpace(string i_Name, string i_Description)
		{
			return int_CreateSpace
				(
				i_Name,
				i_Description,
				GrooveWebServicesV12Helpers.Shared.GROOVE_GENERIC_CREATE_SPACE_TEMPLATE
				);
		}

		/// <summary>
		/// Creates a new workspace.
		/// </summary>
		/// <param name="i_Name">Specifies the name of the created workspace.</param>
		/// <param name="i_Description">Specifies the description of the created workspace.</param>
		/// <param name="i_Type">Groove ComponentURL that defines a Create Space Template, which defines the workspace type and tools for the new space.</param>
		/// <returns>The URI of the created workspace.</returns>
		public string CreateSpace(string i_Name, string i_Description, string i_Type)
		{
			return int_CreateSpace
				(
				i_Name,
				i_Description,
				i_Type
				);
		}

		private string int_CreateSpace(string i_Name, string i_Description, string i_Type)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SPACES_URI,
				Context
				);

			//  Set parameters
			GrooveSpacesWebService.Space NewSpace = new GrooveSpacesWebService.Space();
			NewSpace.Name = i_Name;
			NewSpace.Description = i_Description;

			System.DateTime BeginDateTime = System.DateTime.Now;

            //  Fixup type if running Groove 12
            if (Context.Groove12)
                i_Type = "";

			//  Ask service to create new space
			string SpaceURI = SpacesWebService.Create(NewSpace, i_Type);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::Create, " + TimeSpan.TotalMilliseconds + " ms");
			}

			return SpaceURI;
		}

		/// <summary>
		/// Creates a new workspace from a Groove workspace template or archive.
		/// </summary>
		/// <param name="i_GSAPath">Specifies a file on the local file system that contains the workspace template or archive, for example, "C:\temp\newspace.gsa".</param>
		/// <param name="i_Name">Specifies the name of the created workspace.</param>
		/// <param name="i_Passphrase">Specifies the pass phrase used to decrypt the file. If this parameter is an empty string, the GSA file is opened without a password.</param>
		/// <returns>The URI of the created workspace.</returns>
		public string CreateSpaceFromGSA(string i_GSAPath, string i_Name, string i_Passphrase)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SPACES_URI,
				Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to create new space
			string SpaceURI = SpacesWebService.CreateFromGSAByRef
				(
				i_GSAPath,
				i_Name,
				i_Passphrase
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::CreateFromGSAByRef, " + TimeSpan.TotalMilliseconds + " ms");
			}
			
			return SpaceURI;
		}

		/// <summary>
		/// Creates a new workspace from a Groove workspace template or archive.
		/// </summary>
		/// <param name="i_GSAContents">Byte array. Specifies the contents of the .gsa file containing the workspace template or archive.</param>
		/// <param name="i_Name">Specifies the name of the created workspace.</param>
		/// <param name="i_Passphrase">Specifies the pass phrase used to decrypt the file. If this parameter is an empty string, the GSA file is opened without a password.</param>
		/// <returns>The URI of the created workspace.</returns>
		public string CreateSpaceFromGSA(System.Byte[] i_GSAContents, string i_Name, string i_Passphrase)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SPACES_URI,
				Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to create new space
			string SpaceURI = SpacesWebService.CreateFromGSA
				(
				i_GSAContents,
				i_Name,
				i_Passphrase
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::CreateFromGSA, " + TimeSpan.TotalMilliseconds + " ms");
			}
			
			return SpaceURI;
		}

		/// <summary>
		/// Creates a new Groove File Sharing workspace.
		/// </summary>
		/// <param name="i_FolderPath">Specifies the existing Windows path for the folder to be shared as a Groove workspace.</param>
		/// <param name="i_Name">Specifies the display name of the workspace. This name can be different than Windows folder name. The display name identifies the workspace in the Launchbar and in invitations. </param>
		/// <returns>The URI of the created workspace.</returns>
		public string CreateGrooveFileSharingSpace(string i_FolderPath, string i_Name)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SPACES_URI,
				Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to create new space
			string SpaceURI = SpacesWebService.CreateGrooveFileSharingSpace
				(
				i_FolderPath,
				i_Name
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::CreateGrooveFileSharingSpace, " + TimeSpan.TotalMilliseconds + " ms");
			}
			
			return SpaceURI;
		}

		/// <summary>
		/// Creates an invitation file for a given workspace.
		/// <seealso>You can also use the CreateInvitationFile method on the Space object.</seealso>
		/// </summary>
		/// <param name="i_InvitationFilePath">Specifies a file path on the local file system for the new invitation file, for example, "C:\temp\invitation.grv".</param>
		/// <param name="i_SpaceURI">URI of the workspace.</param>
		/// <param name="i_Role">Specifies the workspace role for the invitation as: "$Telespace.Manager", "$Telespace.Member", or "$Telespace.Guest".</param>
		public void CreateInvitationFileForSpace(string i_InvitationFilePath, string i_SpaceURI, string i_Role)
		{
			string SerializedInvitation = int_SerializeInvitationForSpace
				(
				i_SpaceURI,
				i_Role
				);

			System.IO.FileStream FileStream = null;
			System.IO.StreamWriter StreamWriter = null;

			try
			{
				//  Write serialized invitation to file
				FileStream = new System.IO.FileStream(i_InvitationFilePath, System.IO.FileMode.Create);
				StreamWriter = new System.IO.StreamWriter(FileStream);
				StreamWriter.Write(SerializedInvitation);
			}
			finally
			{
				if (StreamWriter != null)
					StreamWriter.Close();

				if (FileStream != null)
				{
					FileStream.Flush();
					FileStream.Close();
				}

			}
		}


		/// <summary>
		/// Creates contents of an invitation file for a given workspace.
		/// <seealso>You can also use the CreateInvitationFile method on the Space object.</seealso>
		/// </summary>
		/// <param name="i_SpaceURI">URI of the workspace.</param>
		/// <param name="i_Role">Specifies the workspace role for the invitation as: "$Telespace.Manager", "$Telespace.Member", or "$Telespace.Guest".</param>
		/// <returns>String containing the invitation content.</returns>
		public string SerializeInvitationForSpace(string i_SpaceURI, string i_Role)
		{
			return int_SerializeInvitationForSpace
				(
				i_SpaceURI, 
				i_Role
				);
		}

		private string int_SerializeInvitationForSpace(string i_SpaceURI, string i_Role)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				i_SpaceURI,
				Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to create invitation file
			string InvitationFileContents = SpacesWebService.CreateInvitationFile(i_Role);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::CreateInvitationFile, " + TimeSpan.TotalMilliseconds + " ms");
			}

			return InvitationFileContents;
		}

		/// <summary>
		/// Creates a Space object from a workspace URI.
		/// </summary>
		/// <param name="i_SpaceURI">URI of the workspace.</param>
		/// <returns>a Space.</returns>
		public GrooveWebServicesV12Helpers.Space OpenSpace(string i_SpaceURI)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				i_SpaceURI,
				Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to read space
			GrooveSpacesWebService.Space ExistingSpace = SpacesWebService.ReadSpace();

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::ReadSpace, " + TimeSpan.TotalMilliseconds + " ms");
			}

			//  Create helper class
			GrooveWebServicesV12Helpers.Space Space = new GrooveWebServicesV12Helpers.Space
				(
				this,
				ExistingSpace
				);

			return Space;
		}

		/// <summary>
		/// Deletes a workspace.
		/// </summary>
		/// <param name="i_SpaceURI">URI of the workspace.</param>
		/// <param name="i_AllDevices">If true, deletes the workspace from all devices for this identity. If false, only deletes the workspace from the current device.</param>
		/// <param name="i_LastManager">If true, will delete the workspace even if the user is the last manager in the workspace. If false, will delete the space only if the current user is not a manager or there are other members who are managers.</param>
		public void DeleteSpace(string i_SpaceURI, bool i_AllDevices, bool i_LastManager)
		{
			//  Get initialized reference to web service
			GrooveSpacesWebService.GrooveSpaces SpacesWebService = GrooveWebServicesV12Helpers.Space.CreateInitializedSpacesWebService
				(
				m_IdentityURL,
				i_SpaceURI,
				Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to delete space
			SpacesWebService.Delete
				(
				i_AllDevices,
				i_LastManager
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SpacesWebService::Delete, " + TimeSpan.TotalMilliseconds + " ms");
			}

		}

		public string AddAggregatedToolEventListener(GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			return this.int_AddAggregatedToolEventListener
				(
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_TOOL_EVENT_CLASS,
				GrooveWebServicesV12Helpers.EventManager.s_EventURI,
				null,																	// Subscription ID
				"",																		// Query
				GrooveWebServicesV12Helpers.EventManager.DEFAULT_TIME_TO_LIVE_IN_HOURS,
				i_IGrooveWebServicesEventCallback
				);
		}

		public string AddAggregatedToolEventListener(int i_TimeToLive, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			return this.int_AddAggregatedToolEventListener
				(
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_TOOL_EVENT_CLASS,
				GrooveWebServicesV12Helpers.EventManager.s_EventURI,
				null,																	// Subscription ID
				"",																		// Query
				i_TimeToLive,
				i_IGrooveWebServicesEventCallback
				);
		}

		/// <summary>
		///		Note that all string parameters are optional (i.e. use null for default values)
		/// </summary>
		public string AddAggregatedToolEventListener(string i_EventClass, string i_CallbackURI, string i_Query, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			string EventClass = !System.String.IsNullOrEmpty(i_EventClass) ? i_EventClass : GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_TOOL_EVENT_CLASS;
			string CallbackURI = !System.String.IsNullOrEmpty(i_CallbackURI) ? i_CallbackURI : GrooveWebServicesV12Helpers.EventManager.s_EventURI;
            string Query = !System.String.IsNullOrEmpty(i_EventClass) ? i_Query : "";
				
			return this.int_AddAggregatedToolEventListener
				(
				EventClass,
				CallbackURI,
				null,																	// Subscription ID
				Query,
				GrooveWebServicesV12Helpers.EventManager.DEFAULT_TIME_TO_LIVE_IN_HOURS,
				i_IGrooveWebServicesEventCallback
				);
		}

		/// <summary>
		///		Note that all string parameters are optional (i.e. use null for default values)
		/// </summary>
		public string AddAggregatedToolEventListener(string i_EventClass, string i_CallbackURI, string i_Query, int i_TimeToLive, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			string EventClass = !System.String.IsNullOrEmpty(i_EventClass) ? i_EventClass : GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_TOOL_EVENT_CLASS;
			string CallbackURI = !System.String.IsNullOrEmpty(i_CallbackURI) ? i_CallbackURI : GrooveWebServicesV12Helpers.EventManager.s_EventURI;
			string Query = !System.String.IsNullOrEmpty(i_EventClass) ? i_Query : "";
				
			return this.int_AddAggregatedToolEventListener
				(
				EventClass,
				CallbackURI,
				null,																	// Subscription ID
				Query,
				i_TimeToLive,
				i_IGrooveWebServicesEventCallback
				);
		}

		/// <summary>
		///		Note that all string parameters except i_SubscriptionID are optional (i.e. use null for default values)
		/// </summary>
		public void AddAggregatedToolEventListener(string i_EventClass, string i_CallbackURI, string i_Query, string i_SubscriptionID, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			if (System.String.IsNullOrEmpty(i_SubscriptionID))
				throw new System.ArgumentException("Invalid subscription id!");

			string EventClass = !System.String.IsNullOrEmpty(i_EventClass) ? i_EventClass : GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_TOOL_EVENT_CLASS;
			string CallbackURI = !System.String.IsNullOrEmpty(i_CallbackURI) ? i_CallbackURI : GrooveWebServicesV12Helpers.EventManager.s_EventURI;
			string Query = !System.String.IsNullOrEmpty(i_EventClass) ? i_Query : "";
			
			this.int_AddAggregatedToolEventListener
				(
				EventClass,
				CallbackURI,
				i_SubscriptionID,
				Query,
				GrooveWebServicesV12Helpers.EventManager.DEFAULT_TIME_TO_LIVE_IN_HOURS,
				i_IGrooveWebServicesEventCallback
				);
		}

		/// <summary>
		///		Note that all string parameters except i_SubscriptionID are optional (i.e. use null for default values)
		/// </summary>
		public void AddAggregatedToolEventListener(string i_EventClass, string i_CallbackURI, string i_Query, string i_SubscriptionID, int i_TimeToLive, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			if (System.String.IsNullOrEmpty(i_SubscriptionID))
				throw new System.ArgumentException("Invalid subscription id!");

			string EventClass = !System.String.IsNullOrEmpty(i_EventClass) ? i_EventClass : GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_TOOL_EVENT_CLASS;
			string CallbackURI = !System.String.IsNullOrEmpty(i_CallbackURI) ? i_CallbackURI : GrooveWebServicesV12Helpers.EventManager.s_EventURI;
			string Query = !System.String.IsNullOrEmpty(i_EventClass) ? i_Query : "";
			
			this.int_AddAggregatedToolEventListener
				(
				EventClass,
				CallbackURI,
				i_SubscriptionID,
				Query,
				i_TimeToLive,
				i_IGrooveWebServicesEventCallback
				);
		}

		private string int_AddAggregatedToolEventListener(string i_EventClass, string i_CallbackURI, string i_SubscriptionID, string i_Query, int i_TimeToLive, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			string SubscriptionID = i_SubscriptionID;

			if (System.String.IsNullOrEmpty(SubscriptionID))
			{
				SubscriptionID = GrooveWebServicesV12Helpers.EventManager.AddAggregatedEventListener
					(
					Context,
					m_IdentityURL,
					i_EventClass, 
					i_Query,
					this.SpacesURI,
					i_CallbackURI,
					i_TimeToLive,
					i_IGrooveWebServicesEventCallback
					);
			}
			else
			{
				GrooveWebServicesV12Helpers.EventManager.AddAggregatedEventListener
					(
					Context,
					m_IdentityURL,
					i_EventClass, 
					i_Query,
					this.SpacesURI,
					i_CallbackURI,
					SubscriptionID,
					i_TimeToLive,
					i_IGrooveWebServicesEventCallback
					);
			}

			return SubscriptionID;
		}

		public void RemoveAggregatedToolEventListener(string i_SubscriptionID, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback)
		{
			this.RemoveAggregatedToolEventListener
				(
				i_SubscriptionID,
				i_IGrooveWebServicesEventCallback,
				false
				);
		}

		public void RemoveAggregatedToolEventListener(string i_SubscriptionID, GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback i_IGrooveWebServicesEventCallback, bool i_PersistSubscription)
		{
			if (System.String.IsNullOrEmpty(i_SubscriptionID))
				throw new System.ArgumentException("Invalid subscription id!");

			GrooveWebServicesV12Helpers.EventManager.RemoveEventListener
				(
				i_SubscriptionID,
				i_IGrooveWebServicesEventCallback,
				i_PersistSubscription
				);
		}

		#region Space Event Handling

		private void IncrementSpaceSubscriptionCount()
		{
			lock (s_SpaceEventManagerSortedList)
			{
				if (m_SpaceEventManagerCount == 0)
				{
					m_SpaceSubscriptionID = GrooveWebServicesV12Helpers.EventManager.AddEventListener
						(
						Context,
						m_IdentityURL,
						GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SPACE_EVENT_CLASS, 
						this.SpacesURI,
						GrooveWebServicesV12Helpers.EventManager.s_EventURI,
						this
						);
				}

				++m_SpaceEventManagerCount;
			}
		}

		private void DecrementSpaceSubscriptionCount()
		{
			lock (s_SpaceEventManagerSortedList)
			{
				--m_SpaceEventManagerCount;

				if (m_SpaceEventManagerCount == 0)
				{
					GrooveWebServicesV12Helpers.EventManager.RemoveEventListener
						(
						m_SpaceSubscriptionID,
						this
						);

					m_SpaceSubscriptionID = null;
				}
			}
		}

		internal void RaiseSpaceAddedEvent(GrooveSpacesWebService.Space i_Space)
		{
			if (InternalOnSpaceAddedEvent != null)
			{
				GrooveWebServicesV12Helpers.Space Space = new GrooveWebServicesV12Helpers.Space
					(
					this,
					i_Space
					);

				InternalOnSpaceAddedEvent(Space);
			}
		}

		internal void RaiseSpaceRenamedEvent(GrooveSpacesWebService.Space i_Space)
		{
			if (InternalOnSpaceRenamedEvent != null)
			{
				GrooveWebServicesV12Helpers.Space Space = new GrooveWebServicesV12Helpers.Space
					(
					this,
					i_Space
					);

				InternalOnSpaceRenamedEvent(Space);
			}
		}

		internal void RaiseSpaceRemovedEvent(string i_SpaceURI)
		{
			if (InternalOnSpaceRemovedEvent != null)
				InternalOnSpaceRemovedEvent(i_SpaceURI);
		}

		public delegate void OnSpaceAddedDelegate(GrooveWebServicesV12Helpers.Space i_Space);
		internal event OnSpaceAddedDelegate InternalOnSpaceAddedEvent;
		/// <summary>
		/// Event raised when a new workspace is created or joined.
		/// </summary>
		public event OnSpaceAddedDelegate OnSpaceAddedEvent
		{
			add
			{
				IncrementSpaceSubscriptionCount();
				InternalOnSpaceAddedEvent += value;
			}
			remove
			{
				InternalOnSpaceAddedEvent -= value;
				DecrementSpaceSubscriptionCount();
			}
		}

		public delegate void OnSpaceRenamedDelegate(GrooveWebServicesV12Helpers.Space i_Space);
		internal event OnSpaceRenamedDelegate InternalOnSpaceRenamedEvent;
		/// <summary>
		/// Event raised when a workspace is renamed.
		/// </summary>
		public event OnSpaceRenamedDelegate OnSpaceRenamedEvent
		{
			add
			{
				IncrementSpaceSubscriptionCount();
				InternalOnSpaceRenamedEvent += value;
			}
			remove
			{
				InternalOnSpaceRenamedEvent -= value;
				DecrementSpaceSubscriptionCount();
			}
		}

		public delegate void OnSpaceRemovedDelegate(string i_SpaceURI);
		internal event OnSpaceRemovedDelegate InternalOnSpaceRemovedEvent;
		/// <summary>
		/// Event raised when a workspace is deleted.
		/// </summary>
		public event OnSpaceRemovedDelegate OnSpaceRemovedEvent
		{
			add
			{
				IncrementSpaceSubscriptionCount();
				InternalOnSpaceRemovedEvent += value;
			}
			remove
			{
				InternalOnSpaceRemovedEvent -= value;
				DecrementSpaceSubscriptionCount();
			}
		}

		#endregion

		#endregion

		#region GrooveWebServicesV12HelpersBase Implementation

		public override string BindableURL
		{
			get
			{
				if (System.String.IsNullOrEmpty(m_BindableURL))
				{
					//  Sample Identity URI is 'grooveIdentity://sk3wi7rezgnyzv9u5xvys9ccznw9nxjj@', so we strip
					//  off 'grooveIdentity://'
					string IdentityInfo = this.URI;
					int Index = IdentityInfo.LastIndexOf("/") + 1;
					IdentityInfo = IdentityInfo.Substring(Index);

					m_BindableURL = m_Account.BindableURL + "/Identity#" + IdentityInfo;
				}

				return m_BindableURL;
			}
		}

		public override object BindToObject(ref string[] i_URLParts, int i_URLPartIndex)
		{
			object BindResult = null;
			string RelativeURL = i_URLParts[i_URLPartIndex];
			string[] RelativeURLParts = RelativeURL.Split(new char[]{'#'});

			string ObjectType = RelativeURLParts[0];

			if (ObjectType == "Space")
			{
				string SpaceURI = "/GWS/Groove/2.0/Spaces/grooveTelespace/" + RelativeURLParts[1];

				try
				{
					BindResult = this.OpenSpace(SpaceURI);
				}
				catch (System.Exception Exception)
				{
					throw new System.Exception("Unable to find Space '" + SpaceURI +"' (" + Exception.Message + ")");
				}

				//  If there are more url parts, continue binding
				if (i_URLParts.Length > ++i_URLPartIndex)
				{
					GrooveWebServicesV12Helpers.IBindServices IBindServices = (GrooveWebServicesV12Helpers.IBindServices)BindResult;
					BindResult = IBindServices.BindToObject(ref i_URLParts, i_URLPartIndex);
				}
			}
			else
				throw new System.Exception("Unknown identity url part - '" + ObjectType + "'");

			return BindResult;
		}

		#endregion

		#region IGrooveWebServicesEventCallback Members

		public void ProcessEvent(GrooveEventsWebService.Event i_Event)
		{
			switch (i_Event.EventType)
			{
				case GrooveWebServicesV12Helpers.Shared.GROOVE_SPACE_ADD_EVENT_TYPE:
				{
					GrooveEventsWebService.GrooveSpaceAddEventData SpaceAddEventData = (GrooveEventsWebService.GrooveSpaceAddEventData)i_Event.EventData;
					this.RaiseSpaceAddedEvent(SpaceAddEventData.Space);

					break;
				}

				case GrooveWebServicesV12Helpers.Shared.GROOVE_SPACE_DELETE_EVENT_TYPE:
				{
					GrooveEventsWebService.GrooveSpaceDeleteEventData SpaceDeleteEventData = (GrooveEventsWebService.GrooveSpaceDeleteEventData)i_Event.EventData;
					this.RaiseSpaceRemovedEvent(SpaceDeleteEventData.SpaceURI);

					break;
				}

				case GrooveWebServicesV12Helpers.Shared.GROOVE_SPACE_RENAME_EVENT_TYPE:
				{
					GrooveEventsWebService.GrooveSpaceRenameEventData SpaceRenameEventData = (GrooveEventsWebService.GrooveSpaceRenameEventData)i_Event.EventData;
					this.RaiseSpaceRenamedEvent(SpaceRenameEventData.Space);

					break;
				}

				default:
				{
					System.Diagnostics.Debug.WriteLine("[Identity]Unknown event type: " + i_Event.EventType);
					break;
				}
			}
		}

		#endregion
	}
}
